﻿using System;
using System.Diagnostics.Contracts;

namespace O1.Data.Traversal.Expressions
{
    [ContractVerification(true)]
    internal class StringPropertyExpression : PortableExpression
    {
        private static readonly Func<StringProperty, StringProperty, ObservationInterests>[] MethodTable =
          new Func<StringProperty, StringProperty, ObservationInterests>[PortableOperators.Equalities.Count]
            {
                (queryValue, v) => (v.Key == queryValue.Key && (queryValue.Value == v.Value)) ? ObservationInterests.Interested : ObservationInterests.None,
                (queryValue, v) => (v.Key == queryValue.Key && (queryValue.Value != v.Value)) ? ObservationInterests.Interested : ObservationInterests.None,
            };

        private readonly StringProperty property;

        public StringPropertyExpression(StringProperty value, byte portableOperand)
            : base(portableOperand)
        {
            Contract.Requires(PortableOperators.Equalities.Count > portableOperand);
            Contract.Assume(PortableOperators.Equalities.Count == MethodTable.Length);
            this.property = value;
        }

        public override ObservationInterests Evaluate(StringProperty value)
        {
            Contract.Assume(MethodTable[this.Operand] != null);
            return MethodTable[this.Operand](this.property, value);
        }

        [ContractInvariantMethod]
        private void ObjectInvariant()
        {
            Contract.Invariant(PortableOperators.Equalities.Count > this.Operand);
            Contract.Invariant(PortableOperators.Equalities.Count == MethodTable.Length);
            Contract.Invariant(this.Operand < MethodTable.Length);
        }
    }
}
